-- Created		06/02/2009
-- Modified	
-- Author		wilfried.vandenberghe@gmail.com
-- Version		1.0
-- Database	Oracle 10g 

-- TABCONTENT type definition.
-- Used to format content as an array.
CREATE TYPE TABCONTENT UNDER CONTENT 
(	
	-- List of the headers
	headers	CHARLIST,
	
	-- List for the content
	cells	CHAR2LIST,
	
	-- List that contains the size of each column
	col_size INTLIST,
	
	-- 
	-- Constructor without parmeters
	-- 
	CONSTRUCTOR FUNCTION TABCONTENT RETURN SELF AS RESULT,
	
	-- 
	-- Add a header
	-- 
	MEMBER PROCEDURE add_header(header VARCHAR2),
	
	-- 
	-- Add a row to the array
	-- 
	MEMBER PROCEDURE add_row(row CHARLIST),
	
	--
	-- Inherited from CONTENT
	--
	OVERRIDING MEMBER FUNCTION format RETURN LONG
); 
/

CREATE TYPE BODY TABCONTENT IS

	CONSTRUCTOR FUNCTION TABCONTENT RETURN SELF AS RESULT AS
	BEGIN
		RETURN;
	END TABCONTENT;

	MEMBER PROCEDURE add_header(header VARCHAR2) IS
	BEGIN
		IF headers IS NULL THEN
			headers := CHARLIST(header);
			col_size := INTLIST(length(header));
		ELSE
			headers.extend();
			col_size.extend();
			headers(headers.count()) := header;
			col_size(col_size.count()) := length(header);
		END IF;
		
	END add_header;
	
	MEMBER PROCEDURE add_row(row CHARLIST) IS
		idx INTEGER;
	BEGIN
		IF cells IS NULL THEN
			cells := CHAR2LIST(row);
		ELSE
			cells.extend();
			cells(cells.count()) := row;
		END IF;
		
		-- computes column size
		FOR idx IN row.FIRST .. row.LAST LOOP
			IF col_size(idx) < length(row(idx)) THEN
				col_size(idx) := length(row(idx));
			END IF;
		END LOOP;
	END;
	
	OVERRIDING MEMBER FUNCTION format RETURN LONG IS
		tab_size INTEGER := 0;
		csize INTEGER := 0;
		buffer LONG;
		idx INTEGER;
		ridx INTEGER;
		header VARCHAR2(254);
		row CHARLIST;
	BEGIN
		-- computes the total length of the array
		FOR csize IN col_size.FIRST .. col_size.LAST LOOP
			IF csize = col_size.LAST THEN
				tab_size := tab_size + col_size(csize) + 4;
			ELSE
				tab_size := tab_size + col_size(csize) + 3;
			END IF;
		END LOOP;
		
		-- if there is headers
		IF headers IS NOT NULL THEN
			-- first line
			FOR idx IN 1 .. tab_size LOOP
				buffer := buffer || '=';
			END LOOP;
			buffer := buffer || chr(13) || chr(10);
		
			-- headers line
			FOR idx IN headers.FIRST .. headers.LAST LOOP
				IF idx = headers.LAST THEN
					buffer := buffer || '| ' || upper(rpad(headers(idx), col_size(idx))) || ' |';
				ELSE
					buffer := buffer || '| ' || upper(rpad(headers(idx), col_size(idx) + 1));
				END IF;
			END LOOP;
			buffer := buffer || chr(13) || chr(10);
		
			-- second line
			FOR idx IN 1 .. tab_size LOOP
				buffer := buffer || '=';
			END LOOP;
			buffer := buffer || chr(13) || chr(10);
		
			-- If there is content
			IF cells IS NOT NULL THEN
				-- for each line
				FOR ridx IN cells.FIRST .. cells.LAST LOOP
					row := cells(ridx);
					-- for each column
					FOR idx IN row.FIRST .. row.LAST LOOP
						IF idx = row.LAST THEN
							buffer := buffer || '| ' || rpad(row(idx), col_size(idx)) || ' |';
						ELSE
							buffer := buffer || '| ' || rpad(row(idx), col_size(idx) + 1);
						END IF;
					END LOOP;
					buffer := buffer || chr(13) || chr(10);
				END LOOP;
		
				-- last line
				FOR idx IN 1 .. tab_size LOOP
					buffer := buffer || '=';
				END LOOP;
				buffer := buffer || chr(13) || chr(10);
			END IF;
		END IF;
		
		RETURN buffer;
	END;
END;
/
